<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
	</body>
	<script>
		//proxy类似一个拦截器，有两个参数，target、handler
		//target为需要拦截的对象，handler是对拦截到的对象的处理
		//eg
		let pro = new Proxy({},{
			get:function(terget,property){
				return 33;//所有的属性值返回的都是33
			}
		})
		console.log(pro.name,pro.value);
		
		//get方法
		let person = {
			name:'张三',
			age:'18'
		}
		let pro1 = new Proxy(person,{
			get:function(target,property){
				if(property in target){
					return target[property];
				}else{
					throw new ReferenceError(`Property ${property} does not exit.`);
				}
			}
		});
		console.log(pro1.name);
		console.log(pro1.age);
		//console.log(pro1.sex);
		
		//如果一个属性不可配置和不可写，则该属性不能被代理，通过Proxy对象访问该属性会报错
		const target = Object.defineProperties({},{
			//foo readOnly
			foo:{
				value:123,
				writable:false,
				configurable:false
			}
		});
		const handler = {
			get(target,propKey){
				return 'abc';
			}
		}
		const pro2 = new Proxy(target,handler);	
		//console.log(pro2.foo.value);
		
		//set
		let validator = {
			set:function(obj,prop,value){
				if(prop === 'age'){
					if(!Number.isInteger(value)){
						throw new TypeError('The age is not an integer.');
					}
					if(value > 200){
						throw new RangeError('The age seems invalid.');
					}
				}
				//对于满足条件的age属性以及其他属性，直接保存
				obj[prop] = value;
			}
		};
		let man = new Proxy({},validator);
		man.age = 100;
		console.log(man);
		//console.log(man.age = 'young');
		//console.log(man.age = 300);
		
		//apply
		let target1 = function(){
			return 'I am the target';
		}
		let handler1 = {
			apply:function(){
				return 'I am the proxy';
			}
		};
		let p = new Proxy(target1,handler1);
		console.log(p());
		
		//再一个栗子
		let twice = {
			apply(target,ctx,args){
				return Reflect.apply(...arguments) * 2;
			}
		}
		let sum = (left,right) =>{
			left + right;
		}
	</script>
</html>
